package cn.barudisshu.route;


import cn.barudisshu.http.ContentType;
import cn.barudisshu.http.Resource;
import cn.barudisshu.http.servlet.HttpRequest;
import cn.barudisshu.http.servlet.HttpResponse;
import cn.barudisshu.matcher.RestRequestMatch;
import cn.barudisshu.render.RenderFactory;
import cn.barudisshu.result.WebResult;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;

import java.io.File;
import java.lang.reflect.Method;
import java.util.List;

/**
 * ActionInvocation invoke the action
 */
public class RouteInvocation {

    private Route route;
    private Optional<? extends RestRequestMatch> restRequestMatch;
    private HttpRequest request;
    private HttpResponse response;
    private int index = 0;

    public RouteInvocation(Route route, Optional<? extends RestRequestMatch> restRequestMatch, HttpRequest request, HttpResponse
            response) {
        this.route = route;
        this.restRequestMatch = restRequestMatch;
        this.request = request;
        this.response = response;
    }

    public void invoke() {
        try {
            Resource resource = route.getResourceClass().newInstance();
            Method method = route.getMethod();
            ImmutableMap<String,String> param = ImmutableMap.of();
            if(restRequestMatch.isPresent()){
                param = restRequestMatch.get().getPathParams();
            }
            method.setAccessible(true);
            Object invokeResult;

            // TODO: 2017/1/19 执行每个路由对应Class中的对应方法
            //执行方法
            if (route.getAllParamNames().size() > 0) {
                List<String> allParamNames = route.getAllParamNames();
                //执行方法的参数
                Object[] args = new Object[allParamNames.size()];
                int i = 0;
                for (String name : allParamNames) {
                    args[i++] = param.get(name);
                }
                invokeResult = method.invoke(resource, args);
            } else {
                invokeResult = method.invoke(resource);
            }
            //输出结果
            render(invokeResult);
        } catch (Exception e) {
            Throwable cause = e.getCause();
            if (cause == null) {
                cause = e;
            }
        }


    }

    /**
     * 输出内容
     *
     * @param invokeResult invokeResult
     */
    private void render(Object invokeResult) {
        Object result = null;
        //通过特定的webresult返回并携带状态码
        if (invokeResult instanceof WebResult) {
            WebResult webResult = (WebResult) invokeResult;
            response.setStatus(webResult.getStatus());
            result = webResult.getResult();
        } else {
            result = invokeResult;
        }
        String extension = ContentType.JSON; // TODO: 2017/1/19 根据后缀进行渲染
        //file render
        if ((result instanceof File && extension.equals("")) || extension.equals(RenderFactory.FILE)) {
            RenderFactory.getFileRender().render(request, response, result);
        } else
            RenderFactory.get(extension).render(request, response, result);
    }


    public Route getRoute() {
        return route;
    }

    public Optional<? extends RestRequestMatch> getRestRequestMatch() {
        return restRequestMatch;
    }

    public HttpRequest getRequest() {
        return request;
    }

    public HttpResponse getResponse() {
        return response;
    }
}
